dbt Cloud CLIとSQLFluffとGitHub Actionsを用いて、プルリクエスト発行時に自動フォーマッティングしてみた

dbt Cloud CLIとSQLFluffとGitHub Actionsを用いて、プルリクエスト発行時に自動フォーマッティングしてみた

Clock Icon2024.08.14

さがらです。

dbt Cloud CLIとSQLFluffとGitHub Actionsを用いて、プルリクエスト発行時に自動フォーマッティングしてみたので、本記事でまとめてみます。

背景

なぜ「dbt Cloud CLIとSQLFluffとGitHub Actionsを用いて、プルリクエスト発行時に自動フォーマッティング」したいと考えたのかと言うと、「dbt CloudではSQLFluffを使ったフォーマッティングできる機能はあるものの、手動でボタンを押してファイル1つ1つに対してフォーマッティング行うしかないため」です。

これがdbt Coreだと、pre-commitなどを併用してローカルでの開発時にコミットのタイミングでフォーマッティングを自動で行うことができるのですが、dbt Cloudではpre-commitのような機能がありません。

そこで、dbt Cloudで開発を行って自動でフォーマッティングする一つの方法として「dbt Cloud CLIとSQLFluffとGitHub Actionsを用いて、プルリクエスト発行時に自動フォーマッティング」というアイデアに至りました。

(ちょうどよく2024年7月にdbt Cloud CLI経由でSQLFluffが実行できるようになったので、これも使ってみます。これを使うことで、GitHub Actionsでdbt Coreを使わずに済むため、profiles.ymlなどの定義が不要となり楽になります。)

懸念点

ただし、今回の実装には以下の懸念点もあります。ご利用の際はこのあたりのリスクも考慮した上でご利用ください。

  • 良くも悪くもmodels配下のすべてのSQLファイルが定めたSQLFluffのルールに沿ってフォーマッティングされてしまう
  • 今回検証したSQLファイルが少なかったこともあるため動作速度に問題はなかったが、ファイルが多い場合の動作速度がネックになる可能性がある

事前準備:SQLFluff用のファイルの設定

SQLFluffを使用するための各種ファイルを設定していきます。

.sqlfluffファイルをdbt projectのルート階層に追加します。内容はこちらの公式Docを参考にし、dbtのテンプレートを使用するようにしました。

[sqlfluff]
templater = dbt
# This change (from jinja to dbt templater) will make linting slower
# because linting will first compile dbt code into data warehouse code.
runaway_limit = 10
max_line_length = 80
indent_unit = space

[sqlfluff:indentation]
tab_space_size = 4

[sqlfluff:layout:type:comma]
spacing_before = touch
line_position = trailing

[sqlfluff:rules:capitalisation.keywords] 
capitalisation_policy = lower

[sqlfluff:rules:aliasing.table]
aliasing = explicit

[sqlfluff:rules:aliasing.column]
aliasing = explicit

[sqlfluff:rules:aliasing.expression]
allow_scalar = False

[sqlfluff:rules:capitalisation.identifiers]
extended_capitalisation_policy = lower

[sqlfluff:rules:capitalisation.functions]
capitalisation_policy = lower

[sqlfluff:rules:capitalisation.literals]
capitalisation_policy = lower

[sqlfluff:rules:ambiguous.column_references]  # Number in group by
group_by_and_order_by_style = implicit

2024-08-14_08h04_13

次に、.sqlfluffignoreファイルを下記の内容で追加します。

dbt_packages/
macros/
seeds/
target/

dbt Cloud CLIのConfiguration FileをGitHubのリポジトリにSecretとして登録

dbt Cloud CLIをGitHub Actions経由で動かすためには、ランナーの~/.dbt/dbt_cloud.ymlを作る必要があります。

dbt_cloud.ymlにはtoken情報が含まれるため、GitHubのリポジトリでSecretとして登録しておき、GitHub Actionsでジョブ実行時にSecretを参照して~/.dbt/dbt_cloud.ymlを作るようにしていきます。

まず、対象のdbt projectでDevelopConfigure Cloud CLIを押します。

2024-08-14_09h47_12

表示された画面で、Pythonを押した後に、Download CLI configuration fileを押します。(Pythonを押さなくてもよいはずですが、GitHub Actionsで今回pipを使ってインストールするため、念の為押しています。)

2024-08-14_09h54_36

ダウンロードしたdbt_cloud.ymlを加工し、必要なdbt projectの情報だけが含まれるように編集します。完成形としては下図のようになります。

2024-08-14_10h00_53

加工が終わったら、そのファイルの内容をすべて、GitHubの対象リポジトリのActions secrets and variablesからSecretとして登録しておきます。

2024-08-14_10h05_41

2024-08-14_10h07_25

GitHub Actionsの設定

まず、dbt projectのルート階層で.github/workflows/というフォルダを作ります。

2024-08-14_07h29_26

次に、作成したフォルダ内で任意のyamlファイルを作成します。

2024-08-14_07h30_58

作成したyamlファイルの中で、下記のコードを入力します。(なお、このコードの作成にあたってはこちらのPyhonコードの自動フォーマットの記事の内容を参考にさせていただきました。)

name: SQLFluff Formatting

on:
  pull_request:
    types: [opened, synchronize] # プルリクエストがオープン、更新された場合にトリガー

jobs:
  formatter:
    name: formatter
    runs-on: ubuntu-latest # Ubuntu Linux 上で実行
    permissions:
      contents: write # コンテンツに対する書き込み権限を設定
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4 # GitHubリポジトリからコードをチェックアウト
        with:
          ref: ${{ github.head_ref }} # GitHubヘッドリファレンスを指定。開発をしたプルリクエスト元のブランチが参照される
      - name: Set up Python
        uses: actions/setup-python@v4 # Python環境のセットアップ
        with:
          python-version: "3.12" # 使用するPythonバージョンを指定
      - name: Authenticate using service account
        run: |
          mkdir -p ~/.dbt # .dbtディレクトリを作成
          echo "$KEYFILE" > ~/.dbt/dbt_cloud.yml # secretとして登録したdbt_cloud.ymlを元に、ランナーでもdbt_cloud.ymlを作成
        shell: bash
        env:
          KEYFILE: ${{secrets.DBT_CLOUD_CLI_CONFIG_YAML}}
      - name: Install Dependencies
        run: |
          python -m pip install --upgrade pip # pipをアップグレード
          pip install dbt --no-cache-dir # dbt Cloud CLIをインストール
      - name: SQLFluff Fix # sqlfluffを使用してコードをフォーマッティング
        run: dbt sqlfluff fix ./models/* --dialect snowflake # sqlfluffをmodelsフォルダ配下の.sqlファイルに適用
      - name: Auto Commit
        uses: stefanzweifel/git-auto-commit-action@v5 # 自動コミットアクションを使用
        with:
          commit_message: Apply Code Formatter(SQLFluff) # コミットメッセージを指定

挙動を確かめてみた

実際にdbt Cloud経由で開発を行い、SQLFluffを用いた自動フォーマッティングがされるかを確かめてみます。

まず、stg_customers.sqlを下記のようにインデントや大文字小文字が入り乱れているコードにしたうえで、コミットします。

2024-08-14_10h31_47

この状態で、dbt Cloud経由でプルリクエストを発行します。

2024-08-14_07h57_28

すると、先程ymlで定義したジョブがGitHub Actions経由で実行されます。

2024-08-14_11h15_56

この後でプルリクエストに含まれるstg_customers.sqlを見ると、無事にフォーマッティングされた状態でコミットされていました!

2024-08-14_11h16_49

最後に

dbt Cloud CLIとSQLFluffとGitHub Actionsを用いて、プルリクエスト発行時に自動フォーマッティングする方法についてまとめてみました。

プルリクエスト時の自動フォーマッティングは賛否分かれるかもしれませんが、dbt Cloud CLIをGitHub Actionsに組み込む方法については汎用的に使えると思います。一部でも本記事の内容が参考になっていると嬉しいです!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.